package com.choosefine.paycenter.account.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.aliyun.openservices.ons.api.Message;
import com.aliyun.openservices.ons.api.Producer;
import com.aliyun.openservices.ons.api.SendResult;
import com.choosefine.paycenter.account.dao.AccountBillMapper;
import com.choosefine.paycenter.account.dto.*;
import com.choosefine.paycenter.account.enums.RoleType;
import com.choosefine.paycenter.account.service.AccountService;
import com.choosefine.paycenter.account.vo.BizzOrderVo;
import com.choosefine.paycenter.common.enums.*;
import static com.choosefine.paycenter.account.enums.RoleType.*;
import com.choosefine.paycenter.account.model.Account;
import com.choosefine.paycenter.account.model.AccountBill;
import com.choosefine.paycenter.account.service.AccountBillService;
import com.choosefine.paycenter.common.config.ConfigAssember;
import com.choosefine.paycenter.common.constants.ExceptionCodeConstants;
import com.choosefine.paycenter.common.constants.ExceptionMessageConstants;
import com.choosefine.paycenter.common.exception.BusinessException;
import com.choosefine.paycenter.common.utils.ByteArrayStringUtils;
import com.choosefine.paycenter.common.utils.MessageSourceUtils;
import com.choosefine.paycenter.common.utils.PaycenterStringUtils;
import com.choosefine.paycenter.common.utils.SerialNumberUtils;
import com.choosefine.paycenter.pay.api.RechargeService;
import com.choosefine.paycenter.pay.model.TradeOrder;
import com.choosefine.paycenter.pay.service.ChannelService;
import com.choosefine.paycenter.pay.service.PaymentService;
import com.choosefine.paycenter.pay.service.PaymentToTradeOrderService;
import com.choosefine.paycenter.pay.service.TradeOrderService;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.client.RestTemplate;
import tk.mybatis.mapper.entity.Condition;
import tk.mybatis.mapper.entity.Example;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * Comments：账单信息管理
 * Author：DengYouyi
 * Create Date：2017/3/7
 * Modified By：
 * Modified Date：
 * Why & What is modified：
 * Version：v1.0
 */
@Slf4j
@Service
public class AccountBillServiceImpl implements AccountBillService{

    @Autowired
    private AccountBillMapper accountBillMapper;

    @Autowired
    private AccountService accountService;

    @Autowired
    private PaymentService paymentService;

    @Autowired
    private RechargeService rechargeService;

    @Autowired
    private ChannelService channelService;

    @Autowired
    private TradeOrderService tradeOrderService;

    @Autowired
    private PaymentToTradeOrderService paymentToTradeOrderService;

    @Autowired
    private ConfigAssember configAssember;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private SerialNumberUtils serialNumberUtils;

    @Autowired
    private MessageSourceUtils localeMessageSourceUtils;

    @Value("${labour.baseUrl}")
    private String labourBaseUrl;

    @Autowired
    @Qualifier("delayCloseMessageProducer")
    private Producer delayCloseProducer;

    @Value("${aliyun.ons.topic.topicDelayClose}")
    private String topicDelayClose;

    //延迟关闭的小时数单位
    @Value("${sys.pay.delayCloseHour}")
    private long delayCloseHour;

    private static final String API_USERINFO_GET = "labour.userinfo.get";

    private static final String API_COMPANYINFO_GET = "labour.companyinfo.get";


    /**
     *  处理记录账单流水，记录交易双方账户账单流水
     *
     * @param paymentDto
     * @param paySn
     */
    public void recordAccountBill(PaymentDto paymentDto, String paySn){
        if(CollectionUtils.isEmpty(paymentDto.getOrders())){
            throw new BusinessException(ExceptionCodeConstants.PAY_ACCOUNT_TRADEORDER_CANNOT_EMPTY,localeMessageSourceUtils.getMessage( ExceptionMessageConstants.PAY_ACCOUNT_TRADEORDER_CANNOT_EMPTY));
        }
        for (OrderDto orderDto : paymentDto.getOrders()) {
            List<AccountBill> accountBillList = accountBillMapper.selectByBizzSysAndOrderSn(paymentDto.getBizzSys(), orderDto.getOrderSn());
            //已经创建过的账单了，就不能再创建
            if(!CollectionUtils.isEmpty(accountBillList)){
                continue;
            }
            AccountBill mainAcctBill = new AccountBill();//交易主体账号账单

            mainAcctBill.setMainAccountUserCode(paymentDto.getUserCode());
            mainAcctBill.setMainAccountId(paymentDto.getAccountId());
            mainAcctBill.setMainAccountRealName(paymentDto.getAccountRealName());
            mainAcctBill.setMainAccountMobile(PaycenterStringUtils.getInstance().hiddenByChar(paymentDto.getAccountMobile(),3,6,'*'));
            mainAcctBill.setOperName(paymentDto.getOperName());
            boolean isTransferBizzSn = serialNumberUtils.isTransferBizzSn(paymentDto.getBizzSn());
            //特殊处理，转账的业务流水号，与业务订单号是一样的
            if(isTransferBizzSn){
                mainAcctBill.setOrderSn(paymentDto.getBizzSn());
            }else {
                mainAcctBill.setOrderSn(orderDto.getOrderSn());
            }
            mainAcctBill.setFundFlow(FundFlow.OUT);
            mainAcctBill.setTradeMemo(orderDto.getTradeMemo());
            mainAcctBill.setBizzSys(paymentDto.getBizzSys());
            mainAcctBill.setBizzSn(paymentDto.getBizzSn());

            //交易主体账号头像
            final String mainAcctAvatar = getUserAvatarUrl(paymentDto.getUserCode());
            //后续验证下，这个判断应该可以去掉
            if (!(TradeType.RECHARGE.equals(paymentDto.getTradeType()) || TradeType.WITHDRAW.equals(paymentDto.getTradeType()))) {
                Account oppositeAccount = accountService.findByUserCode(orderDto.getUserCode());
                mainAcctBill.setTradeType(paymentDto.getTradeType());
                mainAcctBill.setAmount(orderDto.getAmount());//交易主体资金流出
                mainAcctBill.setOppositeAccountId(oppositeAccount.getId());
                mainAcctBill.setOppositeAccountRealName(oppositeAccount.getRealName());
                mainAcctBill.setOppositeAccountUserCode(oppositeAccount.getUserCode());
                String oppositeAccountMobile = PaycenterStringUtils.getInstance().hiddenByChar(oppositeAccount.getMobile(),3,6,'*');
                mainAcctBill.setOppositeAccountMobile(oppositeAccountMobile);
                //对方账户的头像
                mainAcctBill.setImg(getUserAvatarUrl(oppositeAccount.getUserCode()));
                accountBillMapper.insertSelective(mainAcctBill);

                AccountBill oppoAcctBill = new AccountBill();//交易对方账单
                oppoAcctBill.setBizzSys(paymentDto.getBizzSys());
                oppoAcctBill.setBizzSn(paymentDto.getBizzSn());
                oppoAcctBill.setMainAccountId(oppositeAccount.getId());
                oppoAcctBill.setMainAccountRealName(oppositeAccount.getRealName());
                oppoAcctBill.setMainAccountUserCode(oppositeAccount.getUserCode());
                oppoAcctBill.setMainAccountMobile(oppositeAccountMobile);
                oppoAcctBill.setOppositeAccountId(paymentDto.getAccountId());
                oppoAcctBill.setOppositeAccountRealName(paymentDto.getAccountRealName());
                oppoAcctBill.setOppositeAccountUserCode(paymentDto.getUserCode());
                oppoAcctBill.setOppositeAccountMobile(PaycenterStringUtils.getInstance().hiddenByChar(paymentDto.getAccountMobile(),3,6,'*'));
                oppoAcctBill.setTradeType(paymentDto.getTradeType());
                oppoAcctBill.setFundFlow(FundFlow.IN);
                if(isTransferBizzSn){
                    oppoAcctBill.setOrderSn(paymentDto.getBizzSn());
                }else{
                    oppoAcctBill.setOrderSn(orderDto.getOrderSn());
                }
                oppoAcctBill.setOperName(paymentDto.getOperName());
                oppoAcctBill.setTradeMemo(orderDto.getTradeMemo());
                oppoAcctBill.setAmount(orderDto.getAmount());//交易对方资金流入
                oppoAcctBill.setImg(mainAcctAvatar);//对方账户的头像
                accountBillMapper.insertSelective(oppoAcctBill);
            }
            //发送关闭账单的延迟消息(发送失败，也不影响业务流程)
            try {
                final String body = paymentDto.getBizzSys().toString()+"_"+orderDto.getOrderSn();
                Message msg = new Message(
                        topicDelayClose,
                        "DELAY_CLOSE",
                        ByteArrayStringUtils.getInstance().string2ByteArray(body,"UTF-8"));
                msg.setKey(paymentDto.getBizzSys().toString()+"_"+orderDto.getOrderSn());
                msg.setStartDeliverTime(System.currentTimeMillis()+delayCloseHour * 3600 * 1000);
                SendResult sendResult = delayCloseProducer.send(msg);
                log.info("发送延迟关闭账单消息成功：{}",sendResult);
            }catch (Exception e){
                e.printStackTrace();
                log.info("发送延迟关闭账单消息失败：{}",e);
            }
        }
    }

    @Override
    public void recordAccountBill(AccountBill accountBill) {
        accountBillMapper.insertSelective(accountBill);
    }

    private String getUserAvatarUrl(String userCode){
        try {
            String prefix=StringUtils.substring(userCode,1,2);
            if("PS".equals(prefix)) {//个人租户类型
                String userInfoGetUrl = labourBaseUrl + configAssember.getRestUrl(API_USERINFO_GET);
                Map<String, Object> params = Maps.newHashMap();
                params.put("userCode", userCode);
                HttpEntity<JSONObject> httpEntity = new HttpEntity<>(null, null);
                ResponseEntity<JSONObject> responseEntity = restTemplate.exchange(userInfoGetUrl, HttpMethod.GET, httpEntity, JSONObject.class, params);
                JSONObject userInfoJSONObj = responseEntity.getBody().getJSONObject("data");
                return userInfoJSONObj.getString("headIconUrl");
            }else if("CP".equals(prefix)){//公司类型租户
                String userInfoGetUrl = labourBaseUrl + configAssember.getRestUrl(API_COMPANYINFO_GET);
                Map<String, Object> params = Maps.newHashMap();
                params.put("userCode", userCode);
                HttpEntity<JSONObject> httpEntity = new HttpEntity<>(null, null);
                ResponseEntity<JSONObject> responseEntity = restTemplate.exchange(userInfoGetUrl, HttpMethod.GET, httpEntity, JSONObject.class, params);
                JSONObject companyInfoJSONObj = responseEntity.getBody().getJSONObject("data");
                return companyInfoJSONObj.getString("companyPicurl");
            }
        }catch (Exception e){
            log.error(e.getMessage(),e);

        }
        return null;
    }

    /**
     * 根据业务系统标识与业务方订单号（支付流水号，充值流水号，提现流水号）查询账单列表(交易对方的列表)
     * @param bizzSys
     * @param orderSn
     * @return
     */
    public List<AccountBill> findAccountBillListByBizzSysAndOrderSn(BizzSys bizzSys,String orderSn){
        return accountBillMapper.selectByBizzSysAndOrderSn(bizzSys,orderSn);
    }

    /**
     * 更新账单状态为交易成功
     * @param bizzSys
     * @param orderSn 可以是业务订单号或充值提现流水号
     * @return
     */
    public int updateAccountBillSuccess(BizzSys bizzSys,String orderSn){
        return accountBillMapper.updateStatusByBizzSysAndOrderSn(bizzSys, orderSn, AccountBillStatus.COMPLETE);
    }

    /**
     * 更新账单状态为交易失败
     * @param bizzSys 业务系统标识
     * @param orderSn 可以是业务系统订单号或充值提现流水号
     * @return
     */
    public int updateAccountBillFailure(BizzSys bizzSys,String orderSn){
        return accountBillMapper.updateStatusByBizzSysAndOrderSn(bizzSys, orderSn, AccountBillStatus.FAILURE);
    }

    @Override
    public Map<String, String> findAllTradeTypeByRoleId(Long roleId) {
        Map<String,String> tradeMap = Maps.newHashMap();
        tradeMap.put(TradeType.RECHARGE.name(),TradeType.RECHARGE.getName());
        tradeMap.put(TradeType.WITHDRAW.name(),TradeType.WITHDRAW.getName());
        tradeMap.put(TradeType.TRANSFER.name(),TradeType.TRANSFER.getName());
       if(WK.getValue().longValue() == roleId.longValue()){//建筑工人
           tradeMap.put(TradeType.SALARY.name(),"工资");
       }else if(CL.getValue().longValue() == roleId.longValue()){//班组承包人
           tradeMap.put(TradeType.SHOPPING.name(),TradeType.SHOPPING.getName());
           tradeMap.put(TradeType.SUBPACKAGE.name(),"分包款收款");
       }else if(SU.getValue().longValue() == roleId.longValue()){//分包单位
           tradeMap.put(TradeType.SALARY.name(),"工资发放");
           tradeMap.put(TradeType.SUBPACKAGE.name(),TradeType.SUBPACKAGE.getName());
           tradeMap.put(TradeType.SHOPPING.name(),TradeType.SHOPPING.getName());
           //不展示出来（代付也即商城付款）
           //tradeMap.put(TradeType.PAY_AGENT.name(),TradeType.PAY_AGENT.getName());
       }else if(MG.getValue().longValue() == roleId.longValue()){//项目承包人
           tradeMap.put(TradeType.SHOPPING.name(),TradeType.SHOPPING.getName());
       }else if(CC.getValue().longValue() == roleId.longValue()){//建筑公司
           tradeMap.put(TradeType.SUBPACKAGE.name(),TradeType.SUBPACKAGE.getName());
           tradeMap.put(TradeType.SHOPPING.name(),TradeType.SHOPPING.getName());
           //不展示出来（代付也即商城付款）
           //tradeMap.put(TradeType.PAY_AGENT.name(),TradeType.PAY_AGENT.getName());
       }else{//供应商(材料、设备、设施供应商)
           //这里相对于供应商来说就是收款
           tradeMap.put(TradeType.SHOPPING.name(),"收款");
       }
       return tradeMap;
    }

    @Override
    public BizzOrderVo findBizzOrderByAccountId(Long accountBillId) {
        BizzOrderVo bizzOrderVo = new BizzOrderVo();
        AccountBill accountBill = accountBillMapper.selectBizzSysAndBizzSnById(accountBillId);
        bizzOrderVo.setBizzSys(accountBill.getBizzSys().toString());
        bizzOrderVo.setBizzSn(accountBill.getBizzSn());
        return bizzOrderVo;
    }

    @Override
    public AccountBill findAccountBillById(Long accountBillId) {
        return accountBillMapper.selectByPrimaryKey(accountBillId);
    }

    /**
     * 根据租户账户ID查询账单信息
     * @param accountBillDto
     * @return
     */
    public PageInfo<AccountBill> findPageByAccountId(AccountBillDto accountBillDto){
        Condition condition = new Condition(AccountBill.class);
        condition.setOrderByClause("created_at desc");
        Example.Criteria criteria = condition.createCriteria();
        if(Objects.nonNull(accountBillDto.getMainAccountUserCode())){
            accountService.checkAccountExist(accountBillDto.getMainAccountUserCode());
            criteria.andEqualTo("mainAccountUserCode",accountBillDto.getMainAccountUserCode());
        }
        //账户角色id
        final Long roleId = accountService.findRoleIdByUserCode(accountBillDto.getMainAccountUserCode());
        final boolean isSupplier = isSupplier(roleId);
        final boolean isConstructionCompanyOrLaborSubcontractor = isConstructionCompanyOrLaborSubcontractor(roleId);
        if(accountBillDto.getTradeType()!=null){
            if(isSupplier || isConstructionCompanyOrLaborSubcontractor){//是供应商、建筑公司、分包单位角色的账户
                //这里产品原型只给了商城付款的交易类型,需特殊处理
                if(TradeType.SHOPPING.equals(accountBillDto.getTradeType())){
                    List<TradeType> tradeTypeList = Lists.newArrayList();
                    tradeTypeList.add(TradeType.SHOPPING);
                    tradeTypeList.add(TradeType.PAY_AGENT);
                    criteria.andIn("tradeType",tradeTypeList);
                }else{
                    criteria.andEqualTo("tradeType", accountBillDto.getTradeType());
                }
            }else {
                criteria.andEqualTo("tradeType", accountBillDto.getTradeType());
            }
        }
        if(accountBillDto.getBeforeMonth()!=null){
            Long beforeTime= LocalDateTime.of(LocalDate.now(), LocalTime.now()).minusMonths(accountBillDto.getBeforeMonth()).atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
            criteria.andGreaterThanOrEqualTo("createdAt",DateFormatUtils.format(beforeTime,"yyyy-MM-dd HH:mm:ss"));
        }
        if(StringUtils.isNotBlank(accountBillDto.getTradeMemo())){
            criteria.andLike("tradeMemo","%"+accountBillDto.getTradeMemo()+"%");
        }
        if(accountBillDto.getStartTime() != null){
            criteria.andGreaterThanOrEqualTo("createdAt",DateFormatUtils.format(accountBillDto.getStartTime(),"yyyy-MM-dd HH:mm:ss"));
        }
        if(accountBillDto.getEndTime() != null){
            criteria.andLessThanOrEqualTo("createdAt",DateFormatUtils.format(accountBillDto.getEndTime(),"yyyy-MM-dd HH:mm:ss"));
        }
        if(accountBillDto.getStatus() != null){
            criteria.andEqualTo("status",accountBillDto.getStatus());
        }
        Page<AccountBill> page = PageHelper.startPage(accountBillDto.getPageNum(),accountBillDto.getPageSize());
        accountBillMapper.selectByExample(condition);
        final Map<String, String> tradeTypeMap = findAllTradeTypeByRoleId(roleId);
        if(org.apache.commons.collections.CollectionUtils.isNotEmpty(page.getResult())){
            for(AccountBill accountBill : page.getResult()){
                TradeType tradeType = accountBill.getTradeType();
                tradeType.setName(tradeTypeMap.get(tradeType.name()));
                if(TradeType.SUBPACKAGE.equals(tradeType) && FundFlow.IN.equals(accountBill.getFundFlow())){
                    tradeType.setName("分包款打款");
                }
                if(isSupplier && TradeType.SHOPPING.equals(tradeType) && FundFlow.IN.equals(accountBill.getFundFlow())){
                    //即为商城收款
                    tradeType.setName("收款");
                }
                if(isSupplier && TradeType.PAY_AGENT.equals(tradeType) && FundFlow.IN.equals(accountBill.getFundFlow())){
                    //即为供应商代付货款收入
                    tradeType.setName("收款");
                }
                //建筑公司、分包单位的代付类型，中文名称改为商城付款
                if(isConstructionCompanyOrLaborSubcontractor && TradeType.PAY_AGENT.equals(tradeType) && FundFlow.OUT.equals(accountBill.getFundFlow())){
                    tradeType.setName("商城付款");
                }
                accountBill.setTradeType(tradeType);
            }
        }
        return new PageInfo<>(page);
    }

    public @interface findReceivedPayment{};

    /**
     *  是否为供应商（卖家）
     * @param roleId
     * @return
     */
    private boolean isSupplier(Long roleId){
        if(roleId.longValue() == RoleType.MS.getValue().longValue() || roleId.longValue() == RoleType.ES.getValue().longValue() || roleId.longValue() == RoleType.FS.getValue().longValue()){
            return true;
        }
        return false;
    }

    /**
     *  是否建筑公司或分包单位
     * @param roleId
     * @return
     */
    private boolean isConstructionCompanyOrLaborSubcontractor(Long roleId){
        if(roleId.longValue() == RoleType.CC.getValue().longValue() || roleId.longValue() == RoleType.SU.getValue().longValue()){
            return true;
        }
        return false;
    }

    /**
     * 查询收款明细
     * @param rpaymentDto
     * @return
     */
    public PageInfo<ReceivePaymentDto> findReceivedPayment (ReceivePaymentDto rpaymentDto) {
        //TODO 收款明细待修改
        Condition condition = new Condition(AccountBill.class);
        condition.setOrderByClause("created_at desc");
        Example.Criteria criteria = condition.createCriteria();
        if (Objects.nonNull(rpaymentDto.getUserCode())) {
            criteria.andEqualTo("mainAccountUserCode", rpaymentDto.getUserCode());
        }
        if (rpaymentDto.getTradeType() != null) {
            criteria.andEqualTo("tradeType", rpaymentDto.getTradeType());
        }
        Page<AccountBill> page = PageHelper.startPage(rpaymentDto.getPageNum(), rpaymentDto.getPageSize());
        accountBillMapper.selectByExample(condition);
        Page<ReceivePaymentDto> pageRPayment = new Page<ReceivePaymentDto>(rpaymentDto.getPageNum(),rpaymentDto.getPageSize());
        if (page != null && !CollectionUtils.isEmpty(page.getResult())) {
            pageRPayment.setTotal(page.getTotal());
            for (AccountBill bill : page.getResult()) {
                //Payment payment = paymentService.findByPaySn(bill);
                ReceivePaymentDto pDto = new ReceivePaymentDto();
                BeanUtils.copyProperties(rpaymentDto,pDto);
                pDto.setTradeSn(bill.getOrderSn());
                //if(payment!=null) {
                    //TODO 银行与银行卡号
                   //pDto.setBankCard(getBankcardStr(payment.getBank(),payment.getBankcardNo()));
                //}
                pDto.setBankCard(bill.getBankcardNo());
                pDto.setAmount(bill.getAmount());
                pDto.setTradeTime(bill.getCreatedAt());
                pageRPayment.add(pDto);

            }

        }
        return new PageInfo<>(pageRPayment);
    }

    /**
     * 主动关闭账单(同时会关闭支付单，或充值单)
     * @param accountBillId
     * @return
     */
    @Override
    public void closeAccountBill(String userCode,Long accountBillId) {
        AccountBill accountBill = accountBillMapper.selectByPrimaryKey(accountBillId);
        if(null == accountBill){
            throw new BusinessException(ExceptionCodeConstants.ACCOUNTBILL_NOT_EXISTS,localeMessageSourceUtils.getMessage(ExceptionMessageConstants.ACCOUNTBILL_NOT_EXISTS));
        }
        if(!userCode.equals(accountBill.getMainAccountUserCode())){
            throw new BusinessException(ExceptionCodeConstants.ACCOUNTBILL_CAN_NOT_CLOSE_NOT_BELONG_YOU,localeMessageSourceUtils.getMessage(ExceptionMessageConstants.ACCOUNTBILL_CAN_NOT_CLOSE_NOT_BELONG_YOU));
        }
        final BizzSys bizzSys = accountBill.getBizzSys();
        final String orderSn = accountBill.getOrderSn();
        if(AccountBillStatus.WAIT.equals(accountBill.getStatus())) {
            //会把该账单对应的两条记录（资金流向进出两条）都改为关闭
            accountBillMapper.updateStatusByBizzSysAndOrderSn(accountBill.getBizzSys(),accountBill.getOrderSn(),AccountBillStatus.CLOSED);
        }
        //将对应的交易订单状态也改为关闭
        TradeOrder tradeOrder = tradeOrderService.findTradeOrderByBizzSysAndOrderSn(bizzSys,orderSn);
        if(null != tradeOrder && TradeOrderStatus.WAIT_PAY.equals(tradeOrder.getStatus())) {
            tradeOrderService.updateAsClosedStatusByBizzSysAndOrderSn(bizzSys, orderSn);
        }
        //TODO 如有需要则通知业务方，账单已经关闭了
    }

    /**
     * 被动超时关闭账单(同时会关闭支付单，或充值单)
     */
    @Override
    @Transactional
    public void closeAccountBill(BizzSys bizzSys,String orderSn) {
        List<AccountBill> accountBillList = accountBillMapper.selectByBizzSysAndOrderSn(bizzSys, orderSn);
        if(org.apache.commons.collections.CollectionUtils.isNotEmpty(accountBillList)){
            for(AccountBill accountBill : accountBillList){
                if(AccountBillStatus.WAIT.equals(accountBill.getStatus())) {
                    accountBillMapper.updateStatusByBizzSysAndOrderSn(bizzSys, orderSn,AccountBillStatus.CLOSED);
                }
                TradeOrder tradeOrder = tradeOrderService.findTradeOrderByBizzSysAndOrderSn(bizzSys,orderSn);
                if(null != tradeOrder && TradeOrderStatus.WAIT_PAY.equals(tradeOrder.getStatus())) {
                    tradeOrderService.updateAsClosedStatusByBizzSysAndOrderSn(bizzSys, orderSn);
                }
            }
        }
    }

    @Override
    public void recordBankNameByBizzSysAndOrderSn(BizzSys bizzSys, String orderSn, String bankName) {
        accountBillMapper.updateBankNameByBizzSysAndOrderSn(bizzSys,orderSn,bankName);
    }

    private String getBankcardStr(String bank,String cardNo){
        if(StringUtils.isNoneBlank(bank)&& StringUtils.isNoneBlank(cardNo)) {
            return bank + "(尾号" + StringUtils.substring(cardNo, cardNo.length() - 4, cardNo.length()) + "）";
        }else{
            return "";
        }
    }

    @Override
    public void recordAccountBill(RechargeDto rechargeDto, Account paySn) {
        AccountBill accountBill = new AccountBill();
        String userCode = rechargeDto.getUserCode();
        Account account = accountService.findByUserCode(userCode);
        accountBill.setMainAccountId(account.getId());
        accountBill.setMainAccountUserCode(account.getUserCode());
        accountBill.setMainAccountRealName(account.getRealName());
        accountBill.setMainAccountMobile(PaycenterStringUtils.getInstance().hiddenByChar(account.getMobile(),3,6,'*'));
        accountBill.setFundFlow(FundFlow.IN);
        accountBill.setTradeMemo("充值");
        //若是充值则业务系统标识为SELF(因为是由支付系统自身发起的，故BizzSys为SELF)
        accountBill.setBizzSys(BizzSys.SELF);
        //若是充值则账单的orderSn即为充值流水号
        accountBill.setOrderSn(rechargeDto.getRSn());
        accountBill.setAmount(rechargeDto.getAmount());
        accountBill.setOperName(rechargeDto.getOperName());
        accountBill.setImg(channelService.findLogoByChannelCode(rechargeDto.getChannel()));
        accountBill.setTradeType(TradeType.RECHARGE);
        accountBillMapper.insertSelective(accountBill);
    }
}
